package com.basic.business.common.utils;

import jcifs.CIFSContext;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;
import lombok.extern.slf4j.Slf4j;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 文件处理工具类
 *
 * @author zhaoxy_jn@163.com
 */
@Slf4j
public class FileUtils {

    private static final Map<String, Object> pathLockMap = new ConcurrentHashMap<>();

    static {
        // 设置 SMB 连接池配置
        System.setProperty("jcifs.smb.client.maxConnections", "10000");
        System.setProperty("jcifs.smb.client.soTimeout", "3000000");
    }

    /**
     * 创建文件夹
     */
    public static void createDirectories(String dirPath) throws IOException {
        CIFSContext cifsContext = null;
        try {
            cifsContext = CifsContextPool.borrowContext();
            SmbFile smbDir = new SmbFile(dirPath, cifsContext);

            if (!smbDir.exists()) {
                smbDir.mkdirs();
            }
        } catch (Exception e) {
            throw new IOException("创建远程SMB文件夹失败，路径：" + dirPath);
        } finally {
            if (cifsContext != null) {
                if (cifsContext instanceof Closeable) {
                    ((Closeable) cifsContext).close();
                }
                CifsContextPool.returnContext(cifsContext);
            }
        }
    }




    /**
     * 从HTTP下载文件到SMB
     * @param httpUrl 网络路径
     * @param smbPath 共享路径
     */
    public static String downloadFileFromHttpToSmb(String httpUrl, String smbPath, String imgId, long sid) throws Exception {
        // 获取路径锁对象（若无则创建）
        Object lock = pathLockMap.computeIfAbsent(smbPath, k -> new Object());

        HttpURLConnection httpConn = null;
        InputStream inputStream = null;
        SmbFileOutputStream smbOutputStream = null;
        CIFSContext cifsContext = null;
        String uniqueSmbPath;

        synchronized (lock) { // 同步整个下载过程
            try {
                // 打开HTTP连接
                URL url = new URL(httpUrl);
                httpConn = (HttpURLConnection) url.openConnection();
                httpConn.setRequestMethod("GET");
                httpConn.setConnectTimeout(30000);
                httpConn.setReadTimeout(30000);

                // 检查HTTP响应码
                int responseCode = httpConn.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    // 读取HTTP响应流
                    inputStream = httpConn.getInputStream();

                    // 生成唯一的SMB文件路径（此时已在同步块内）
                    uniqueSmbPath = getUniqueFilePath(smbPath);

                    // 创建SMB文件对象
                    cifsContext = CifsContextPool.borrowContext();
                    SmbFile smbFile = new SmbFile(uniqueSmbPath, cifsContext);

                    // 写入文件（同步保护）
                    try (SmbFileOutputStream smbOutputStreamLocal = new SmbFileOutputStream(smbFile)) {
                        smbOutputStream = smbOutputStreamLocal;
                        byte[] buffer = new byte[4096];
                        int bytesRead;
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            smbOutputStream.write(buffer, 0, bytesRead);
                        }
                    }
                } else {
                    throw new RuntimeException("下载文件失败. 状态码: " + responseCode);
                }
            } catch (Exception e) {
                CompletableFuture.runAsync(() ->
                        DingTalkUtils.send(
                                String.format("下载文件传输到SMB失败，系统单号：%s, 素材编码：%s，路径：%s", sid, imgId, httpUrl),
                                "RPA",
                                ""
                        )
                );
                throw new RuntimeException(String.format("下载失败，素材编码：%s", imgId), e);
            } finally {
                // 资源释放（仍在同步块内）
                if (cifsContext != null) {
                    CifsContextPool.returnContext(cifsContext);
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                if (smbOutputStream != null) {
                    smbOutputStream.close();
                }
                if (httpConn != null) {
                    httpConn.disconnect();
                }
            }
        }
        return uniqueSmbPath;
    }

    /**
     * 获取唯一文件路径
     */
    public static String getUniqueFilePath(String smbPath) throws Exception {
        // 获取路径锁对象（若无则创建）
        Object lock = pathLockMap.computeIfAbsent(smbPath, k -> new Object());

        CIFSContext cifsContext = null;
        try {
            synchronized (lock) {
                // 从连接池获取 CIFSContext
                cifsContext = CifsContextPool.borrowContext();
                SmbFile smbFile = new SmbFile(smbPath, cifsContext);

                // 如果文件不存在，直接返回原路径
                if (!smbFile.exists()) {
                    return smbPath;
                }

                // 获取父目录和文件名
                SmbFile uniqueFile = getUniqueFile(smbFile, cifsContext);

                // 返回唯一文件的绝对路径
                return uniqueFile.getCanonicalPath();
            }
        } catch (Exception e) {
            throw new Exception("获取唯一文件路径失败，路径：" + smbPath, e);
        } finally {
            // 归还 CIFSContext 到连接池
            if (cifsContext != null) {
                CifsContextPool.returnContext(cifsContext);
            }
        }
    }

    /**
     * 获取唯一文件
     */
    private static SmbFile getUniqueFile(SmbFile smbFile, CIFSContext cifsContext) throws MalformedURLException, SmbException {
        String parentDir = smbFile.getParent();
        String fileName = smbFile.getName();

        // 分离文件名和扩展名
        String baseName = fileName.substring(0, fileName.lastIndexOf('.'));
        String extension = fileName.substring(fileName.lastIndexOf('.'));

        int index = 1;
        String uniqueFileName;
        SmbFile uniqueFile;
        do {
            // 生成唯一文件名
            uniqueFileName = baseName + "(" + index + ")" + extension;
            uniqueFile = new SmbFile(parentDir + uniqueFileName, cifsContext);
            index++;
        } while (uniqueFile.exists());
        return uniqueFile;
    }

    /**
     * 根据Windows共享路径删除文件或文件夹
     *
     * @param smbPath SMB路径，可以是文件或文件夹
     */
    public static void deleteFromSmb(String smbPath, String shortId) {
        CIFSContext cifsContext = null;
        try {
            if (smbPath == null || smbPath.isEmpty() || StringUtils.equals(smbPath, "null/")) {
                return;
            }

            cifsContext = CifsContextPool.borrowContext();
            SmbFile smbFile = new SmbFile(smbPath, cifsContext);

            if (!smbFile.exists()) {
                return; // 如果路径不存在，直接返回
            }

            if (smbFile.isFile()) {
                // 如果是文件，删除文件
                smbFile.delete();
                // 检查并删除空文件夹
                deleteEmptyParentFolder(smbFile);
            } else if (smbFile.isDirectory()) {
                // 如果是文件夹，递归删除文件夹及其内容
                deleteFolder(smbFile);
            }
        } catch (Exception e) {
            CompletableFuture.runAsync(() -> DingTalkUtils.send(String.format("删除SMB文件失败，内部单号：%s，路径：%s", shortId, smbPath), "RPA", ""));
            throw new RuntimeException("删除SMB文件失败，路径：" + smbPath, e);
        } finally {
            if (cifsContext != null) {
                // 归还连接至连接池
                CifsContextPool.returnContext(cifsContext);
            }
        }
    }

    /**
     * 递归删除文件夹及其内容
     *
     * @param folder 要删除的文件夹
     */
    private static void deleteFolder(SmbFile folder) throws Exception {
        try {
            if (!folder.exists() || !folder.isDirectory()) {
                return;
            }

            if (folder.isDirectory()) {
                SmbFile[] files = folder.listFiles();
                if (files != null) {
                    for (SmbFile file : files) {
                        if (file.isDirectory()) {
                            deleteFolder(file);
                        } else {
                            file.delete();
                        }
                    }
                }
            }

            // 删除空文件夹
            folder.delete();
        } catch (Exception e) {
            throw new Exception("删除SMB文件夹失败，路径：" + folder.getPath(), e);
        }
    }

    /**
     * 删除空父文件夹
     *
     * @param smbFile 文件或文件夹对象
     */
    private static void deleteEmptyParentFolder(SmbFile smbFile) throws Exception {
        CIFSContext cifsContext = null;
        try {
            if (smbFile == null) return;

            String parentPath = smbFile.getParent();
            if (parentPath == null) return;

            cifsContext = CifsContextPool.borrowContext();
            SmbFile parentFolder = new SmbFile(parentPath, cifsContext);

            if (parentFolder.exists() && parentFolder.isDirectory() && parentFolder.list().length == 0) {
                parentFolder.delete();
            }
        } finally {
            if (cifsContext != null) {
                CifsContextPool.returnContext(cifsContext);
            }
        }
    }

    /**
     * 重命名SMB路径
     */
    public static void renameSmbPath(String originalPath, String newPath){
        if (originalPath == null || newPath == null) {
            throw new IllegalArgumentException("路径不能为空");
        }

        // 检查并规范化路径
        CIFSContext cifsContext = null;
        try {
            cifsContext = CifsContextPool.borrowContext();
            SmbFile originalSmbFile = new SmbFile(originalPath, cifsContext);

            // 确保新路径有效
            SmbFile newSmbFile = new SmbFile(newPath, cifsContext);

            // 执行重命名操作
            originalSmbFile.renameTo(newSmbFile);


        } catch (Exception e) {
            throw new RuntimeException("修改远程SMB文件夹名称失败", e);
        }finally {
            if (cifsContext != null) {
                // 归还连接至连接池
                CifsContextPool.returnContext(cifsContext);
            }
        }
    }

}
